﻿define([
        "dojo/_base/connect",
        "dojo/_base/declare",
        "dojo/_base/lang",
        "dojo/_base/Deferred",
        "dojo/dom-attr",
        "dojo/json",
        "dojo/_base/array",
        "dojo/dnd/Source",
        "dijit/focus",
        "dijit/registry",
        "dijit/_CssStateMixin",
        "dijit/_Widget",
        "dijit/_TemplatedMixin",
        "dijit/_WidgetsInTemplateMixin",
// epi.cms
        "epi-cms/legacy/LegacyDialogPopup",
        "epi-cms/widget/_HasChildDialogMixin",
        "epi/epi",
        "epi/dependency",
        "epi/routes",
        "epi/string",
        "epi/shell/widget/_ValueRequiredMixin",
        "epi/shell/dnd/Target",
        "epi/shell/widget/dialog/Confirmation",
        "ow-epi-listProperty/widgets/ListPropertyEditorWidget",
        "ow-epi-listProperty/widgets/ListItemPropertyWidget",
        "dojo/text!./ListPropertyWidget.html",
        "xstyle/css!./ListPropertyWidget.css"
    ],
    function (
        connect,
        declare,
        lang,
        Deferred,
        domAttr,
        json,
        array,
        DndSource,
        focusManager,
        registry,
        _CssStateMixin,
        _Widget,
        _TemplatedMixin,
        _WidgetsInTemplateMixin,
        LegacyDialogPopup,
        _HasChildDialogMixin,
        epi,
        dependency,
        routes,
        epiString,
        _ValueRequiredMixin,
        Target,
        Confirmation,
        ListPropertyEditorWidget,
        ListItemPropertyWidget,
        template
    ) {

        return declare("ow-epi-listProperty.widgets.ListPropertyWidget", [_Widget, _TemplatedMixin, _WidgetsInTemplateMixin,
                _CssStateMixin, _ValueRequiredMixin, _HasChildDialogMixin], {
                    templateString: template,

                    helptext: "List of items",

                    intermediateChanges: false,

                    baseClass: 'list-property',

                    value: null,

                    _formValues: [],

                    _listItemWidgetType: null,

                    listItemConstructorFunction: null,

                    postMixInProperties: function () {
                        this.inherited(arguments);
                        if (typeof this.readOnly === 'undefined') {
                            this.readOnly = false;
                        }
                        
                        this.listItemConstructorFunction = ListItemPropertyWidget;
                    },

                    postCreate: function () {
                        // call base implementation
                        this.inherited(arguments);

                        // drag items support
                        this.dndSource = new DndSource(this.nodeItemsCollection, {
                            //creator: lang.hitch(this, this._dndSourceItemCreator),
                            copyOnly: true,
                            selfAccept: false,
                            selfCopy: false,
                            accept: ['listItem']
                        });

                        // drop on widget support
                        if (this.widgetDropAreaNode && this.onWidgetDropData) {
                            this.acceptDataTypes = this.acceptDataTypes || [];
                            this._dropTarget = new Target(this.widgetDropAreaNode, {
                                accept: this.acceptDataTypes,
                                createItemOnDrop: false,
                                readOnly: this.readOnly
                            });

                            this.connect(this._dropTarget, "onDropData", this.onWidgetDropData);
                        }
                    },

                    isValid: function () {
                        if (this.readOnly) {
                            return true;
                        }

                        if (this._formValues.length < this.listSettings.minimumElements) {
                            this.missingMessage = 'There should be at least ' + this.listSettings.minimumElements + ' elements';
                            return false;
                        }
                        return true;
                    },

                    _setValueAttr: function (value) {
                        this._set("value", value);

                        if (json.stringify(value) == json.stringify(this._formValues)) {
                            return; // DOM update is not necessary
                        }

                        if (value) {
                            this._formValues = value;
                            this._refreshUI();

                        } else {
                            this._formValues = [];
                        }
                    },

                    _refreshUI: function () {
                        dojo.empty(this.nodeItemsCollection);
                        for (var i = 0; i < this._formValues.length; i++) {
                            this._createItemNode(this._formValues[i]);
                        }

                        if (this.dndSource)
                            this.dndSource.sync();
                    },

                    _setReadOnlyAttr: function (value) {
                        this._set("readOnly", value);

                        domAttr.set(this.nodeAdd, 'disabled', value.toString());

                        if (value) {
                            dojo.addClass(this.domNode, 'disabled');
                        } else {
                            dojo.removeClass(this.domNode, 'disabled');
                        }

                        for (var i = 0; i < this.nodeItemsCollection.childNodes.length; i++) {
                            registry.byNode(this.nodeItemsCollection.childNodes[i]).set('readOnly', value);
                        }
                    },

                    _setStateAttr: function (value) {
                        this._set("state", value);
                    },

                    // Setter for intermediateChanges
                    _setIntermediateChangesAttr: function (value) {
                        this._set("intermediateChanges", value);
                    },

                    destroy: function () {
                        if (this._dialog) {
                            this._dialog.destroyRecursive();
                            delete this._dialog;
                        }

                        this.inherited(arguments);
                    },

                    onChange: function (value) {
                        // Event
                    },

                    addNewItem: function (newItem) {
                        if (this.readOnly) {
                            return;
                        }

                        if (!newItem) {
                            newItem = null;
                        }

                        if (this._formValues.length >= this.listSettings.maximumElements) {
                            alert('You can add up to ' + this.listSettings.maximumElements.max + ' items.');
                            return;
                        }
                        focusManager.focus(this.mainContainer);
                        this._showEditor(newItem);
                    },

                    _showEditor: function (editItem) {
                        var itemIndex = editItem ? array.indexOf(this._formValues, editItem) : -1;
                        this._dialog = new ListPropertyEditorWidget(
                            {
                                listMetadata: this.metadata.customEditorSettings.listModelProperties,
                                editItem: editItem,
                                itemIndex: itemIndex,
                                readOnly: this.readOnly
                            });

                        this.connect(this._dialog, "onCallback", this._onDialogCallback);
                        this.connect(this._dialog, 'onHide', this._onDialogHide);
                        this.isShowingChildDialog = true;
                        this._dialog.show();
                    },

                    _onDialogCallback: function (value) {
                        // cancel
                        if (!value) {
                            return;
                        }

                        // insert
                        if (value.closeAction === "insert" && value.formValues) {

                            if (value.itemIndex < 0) {
                                this._formValues.push(value.formValues);
                                this._createItemNode(value.formValues);
                                this.dndSource.sync();
                            } else {
                                this._formValues[value.itemIndex] = value.formValues;
                                registry.byNode(this.nodeItemsCollection.childNodes[value.itemIndex]).set('listItem', value.formValues);
                            }

                            this._set("value", this._formValues);
                            this.onChange(this._formValues);
                        }
                    },

                    _onDialogHide: function () {
                        this.isShowingChildDialog = false;

                        this._dialog.destroyRecursive();
                        delete this._dialog;

                        focusManager.focus(this.mainContainer);
                    },

                    _createItemNode: function createItemNodeF(listItem) {
                        var listItemId = registry.getUniqueId('listItem');
                        var itemNode = dojo.create('div', { id: listItemId }, this.nodeItemsCollection, "last");

                        var widgetSettings = { list: this._formValues };
                        if (this.itemWidgetSettings) {
                            lang.mixin(widgetSettings, this.itemWidgetSettings);
                        }

                        var listItemWidget = new this.listItemConstructorFunction(widgetSettings, itemNode);
                        listItemWidget.set('itemDisplayNamePropertyName', this.itemDisplayNamePropertyName);
                        listItemWidget.set('listItem', listItem);

                        var self = this;

                        this.connect(listItemWidget, "onEditItem", function onEditItemF(itemToEdit) {
                            self._showEditor(itemToEdit);
                        });

                        this.connect(listItemWidget, "onDeleteItem", function onDeleteItemF(listItemToDelete) {
                            if (self.readOnly) {
                                return;
                            }

                            focusManager.focus(this.mainContainer);
                            this.isShowingChildDialog = true;

                            var dialog = new Confirmation({
                                description: "Are you sure that you want to remove selected item ?",
                                onAction: function (confirmed) {
                                    self.isShowingChildDialog = false;

                                    if (confirmed) {
                                        self._formValues = dojo.filter(self._formValues, function (item, index) {
                                            return item !== listItemToDelete;
                                        });

                                        self._set("value", this._formValues);
                                        self.onChange(self._formValues);
                                        listItemWidget.destroy();
                                        focusManager.focus(this.mainContainer);
                                    }
                                }
                            });

                            dialog.connect("onHide", function () {
                                dialog.destroyRecursive();
                            });

                            dialog.show();
                        });

                        // handle sorting items
                        this.connect(listItemWidget, 'onDropItem', function (listItemParam, dndSourceItemParam) {
                            if (this.readOnly) {
                                return;
                            }
                            var sourceDndItemIndex = json.parse(dndSourceItemParam).itemIndex;
                            var targetDndItemIndex = array.indexOf(this._formValues, listItemParam);

                            if (sourceDndItemIndex !== targetDndItemIndex) {
                                var tmpItem = this._formValues[sourceDndItemIndex];
                                this._formValues.splice(sourceDndItemIndex, 1);
                                this._formValues.splice(targetDndItemIndex, 0, tmpItem);

                                //dojo.place(this.nodeItemsCollection.childNodes[targetDndItemIndex], this.nodeItemsCollection.childNodes[sourceDndItemIndex], "before");
                                this._refreshUI();

                                this._set("value", this._formValues);
                                this.onChange(this._formValues);
                            }
                        });
                    }
                });
    });